/*********************************************************************************
 * Software License Agreement (BSD License)
 * Copyright (c) 2012, Carlos D. Correa (info@ngraph.org)
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of netzen nor the
 *    names of its contributors may be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *********************************************************************************/
#include "qMappingEditor.h"

#include <QTableWidget>
#include <QTableView>
#include <QStandardItemModel>
#include <QVBoxLayout>
#include <QItemDelegate>
#include <QComboBox>
#include <QHeaderView>
#include <QPushButton>
#include "propertyInspectorDelegate.h"
#include <assert.h>

extern PropertyInspectorDelegate * createDelegate(Controller *controller,  QWidget *parent);
extern QStandardItemModel * createListModel(string list, Controller *controller);


QMappingEditor::QMappingEditor(Controller *controller, QWidget*parent):QWidget(parent) {
    this->controller = controller;
    assert(controller);
    controller->addPropertyListener(this);

    table = new QTableView();

    model = new QStandardItemModel();
    iTableRowCnt = 0;

    table->setModel(model);


    delegate = createDelegate(controller, this);

    /*
    delegate = new ComboBoxDelegate();
    updateDelegate(nodeProperties, 0, "node");
    updateDelegate(edgeProperties, 1, "edge");
    updateDelegate(colormaps, 2, "colormap");
  */

    vector<string> properties = controller->getVirtualProperties();
    mapPropIndex.clear();

    for(unsigned int i=0;i<properties.size();i++) {
			string value = controller->getVirtualProperty(properties[i]);
			string prefix = Controller::addVirtualPrefix("");
			if(properties[i].find(prefix)==string::npos) continue;
			string name = properties[i].substr(prefix.length());

			QStandardItem *item1 = new QStandardItem(QString(name.c_str()));
			item1->setEditable(false);
			model->setItem(i, 0, item1);
			QStandardItem *item2 = new QStandardItem(QString(value.c_str()));
			model->setItem(i, 1, item2);

			int seltype = PROPERTY_SELECTION;
			QStandardItem *item3 = new QStandardItem(QString("%0").arg(seltype));
			model->setItem(i,2, item3);

			string type = controller->getVirtualPropertyType(properties[i]);
			QStandardItem *item4 = new QStandardItem(QString(type.c_str()));
			model->setItem(i, 3, item4);

			QStandardItem *item5 = new QStandardItem(QString(properties[i].c_str()));
			model->setItem(i, 4, item5);

			mapPropIndex[properties[i]] = i;
    }
    iTableRowCnt = properties.size();

    model->setHeaderData(0, Qt::Horizontal, QString("Visual Property"));
    model->setHeaderData(1, Qt::Horizontal, QString("Data Property"));

    table->setItemDelegate(delegate);
    table->setEditTriggers(QAbstractItemView::AllEditTriggers);
    table->setColumnHidden(2, true); //true //property type index
    table->setColumnHidden(3, true); //true //edge property or node property
		table->setColumnHidden(4, true); //true //full name of property
    table->resizeColumnToContents(0);
    //table->resizeColumnToContents(1);
    table->horizontalHeader()->setStretchLastSection(true);

    connect(model, SIGNAL(itemChanged(QStandardItem *)), SLOT(mappingChanged(QStandardItem *)));

    QWidget *box = new QWidget(this);
    QHBoxLayout * hlayout = new QHBoxLayout();
    propertyBox = new QLineEdit(box);
    typesCombo = new QComboBox(box);
    QPushButton *add = new QPushButton("+");
    typesCombo->addItem("node");
    typesCombo->addItem("edge");
    typesCombo->addItem("colormap");
    hlayout->addWidget(propertyBox);
    hlayout->addWidget(typesCombo);
    hlayout->addWidget(add);
    box->setLayout(hlayout);
    connect(propertyBox, SIGNAL(returnPressed()),this, SLOT(newProperty()));
    connect(add, SIGNAL(clicked()),this, SLOT(newProperty()));

    QVBoxLayout *layout = new QVBoxLayout();
    layout->addWidget(box);
    layout->addWidget(table);
    setLayout(layout);
}

void QMappingEditor::newProperty() {
		string property = propertyBox->text().toStdString();
    string fullproperty = Controller::addVirtualPrefix(propertyBox->text().toStdString());
    string type = typesCombo->currentText().toStdString();
    QList<QStandardItem*>list;
    list.append(new QStandardItem(QString(property.c_str())));
    list.append(new QStandardItem(QString("Default")));
    list.append(new QStandardItem(QString("%0").arg(PROPERTY_SELECTION)));
    list.append(new QStandardItem(QString(type.c_str())));
		list.append(new QStandardItem(QString(fullproperty.c_str())));
    model->appendRow(list);
    controller->addVirtualProperty(fullproperty, type);

    this->mapPropIndex[fullproperty] = this->iTableRowCnt;
    iTableRowCnt++;
}

/**
 Having to update here may give problems in the future, if we change the delegate.
 i.e., forget to update here changes in the PropertyDelegate and viceversa.
 Todo: centralize this somehow
 **/
void QMappingEditor::updateDelegate(string name) {
	QStandardItemModel *listModel = createListModel(name, controller);
	delegate->addStringModel(name, listModel);

    // update in table.
    if( this->mapPropIndex.find(name)!=mapPropIndex.end() ){
        int iIndex = this->mapPropIndex[name];
        string value = controller->getVirtualProperty(name);
        QStandardItem *item2 = new QStandardItem(QString(value.c_str()));
        model->setItem(iIndex, 1, item2);
    }
}


void QMappingEditor::propertyChanged(string name) {
    updateDelegate(name);
}


QMappingEditor::~QMappingEditor() {  
}

void QMappingEditor::mappingChanged(QStandardItem *item) {

    int row = item->index().row();

    string value = item->data(Qt::EditRole).toString().toStdString();
    QStandardItem *itemProp = item->model()->item(row,4);
    string property = itemProp->data(Qt::EditRole).toString().toStdString();

    controller->setVirtualProperty(property, value);
    controller->updateRender();
    //printf("[QMAPPINGEDITOR] Mapping %s to %s\n", property.c_str(), value.c_str());
}
